1 package net.sf.bse;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import java.io.ByteArrayInputStream;
27 import java.io.FileOutputStream;
28 import java.io.PrintStream;
29 import java.math.BigInteger;
30 import java.security.KeyFactory;
31 import java.security.PrivateKey;
32 import java.security.cert.X509Certificate;
33 import java.security.spec.PKCS8EncodedKeySpec;
34 import java.util.Collection;
35 import java.util.Hashtable;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.StringTokenizer;
40
41 import org.bouncycastle.asn1.DERConstructedSequence;
42 import org.bouncycastle.asn1.DERIA5String;
43 import org.bouncycastle.asn1.x509.GeneralName;
44 import org.bouncycastle.asn1.x509.GeneralNames;
45 import org.bouncycastle.asn1.x509.X509Extensions;
46 import org.bouncycastle.asn1.x509.X509Name;
47 import org.bouncycastle.jce.PKCS10CertificationRequest;
48 import org.bouncycastle.jce.X509KeyUsage;
49 import org.bouncycastle.jce.X509V3CertificateGenerator;
50 import org.bouncycastle.jce.provider.X509CertificateObject;
51
52 /***
53 * Command to sign a leaf certificate.
54 *
55 * @author Bill Foote (bill.foote@sun.com)
56 * @author Aleksi Peebles (aleksi.peebles@infocast.fi)
57 * @version $Revision: 1.3 $ $Date: 2004/05/06 10:00:34 $
58 */
59
60 public class SignLeafCertificate extends Command
61 {
62 public SignLeafCertificate(Map args)
63 {
64 super(args);
65 }
66
67 public void usageMessage(PrintStream out)
68 {
69 out.println(
70 "Command: sign\n\n" +
71
72 " Signs an MHP certificate\n\n" +
73
74 " Arguments:\n\n" +
75
76 " csrFile: Certificate signing request file\n" +
77 " certFile: File containing signer's X509 certificate\n" +
78 " keyFile: File containing signer's private key\n" +
79 " validFrom: Date cert to be valid from, in dd/mm/yyyy format\n" +
80 " validUntil: Date cert to be valid until, in dd/mm/yyyy format\n" +
81 " file: Where to store the results\n\n" +
82
83 " Optional arguments:\n\n" +
84 " leaf: Whether the certificate is a leaf (true, default)\n" +
85 " or not (false)\n");
86 }
87
88 public String[] getRequiredArgs()
89 {
90 return new String[] { "csrFile:", "certFile:", "keyFile:",
91 "validFrom:", "validUntil:", "file:" };
92 }
93
94 public String[] getOptionalArgs()
95 {
96 return new String[] { "leaf:"};
97 }
98
99 private X509CertificateObject readIssuerCert() throws Exception
100 {
101 String fn = getArg("certFile:");
102 System.out.println("Reading issuer cert from " + fn + ".");
103 ByteArrayInputStream bis =
104 new ByteArrayInputStream(readBytesFromFile(fn));
105 return readX509(bis);
106 }
107
108 private PrivateKey readIssuerKey() throws Exception
109 {
110 String fn = getArg("keyFile:");
111 System.out.println("Reading issuer key from " + fn + ".");
112 byte[] encoded = readBytesFromFile(fn);
113 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(encoded);
114 KeyFactory fact = KeyFactory.getInstance("RSA", "BC");
115 PrivateKey key = fact.generatePrivate(spec);
116 return key;
117 }
118
119 public void run() throws Exception
120 {
121 String token = getArg("leaf:");
122 boolean isLeaf = token == null || token.equals("true");
123 System.out.println(
124 "Signing " + (isLeaf ? "leaf " : "") + "certificate request.");
125
126
127 getDateArg("validFrom:");
128 getDateArg("validUntil:");
129
130 X509CertificateObject issuerCert = readIssuerCert();
131 PrivateKey issuerKey = readIssuerKey();
132
133
134 PKCS10CertificationRequest csr = new PKCS10CertificationRequest(
135 readBytesFromFile(getArg("csrFile:")));
136
137
138 String subject =
139 csr.getCertificationRequestInfo().getSubject().toString();
140 String c = null, cn = null, o = null, e = null;
141 StringTokenizer st = new StringTokenizer(subject, ",");
142 while (st.hasMoreTokens())
143 {
144 token = st.nextToken();
145 if (token.startsWith("C="))
146 {
147 c = token.substring(2);
148 }
149 else if (token.startsWith("CN="))
150 {
151 cn = token.substring(3);
152 }
153 else if (token.startsWith("O="))
154 {
155 o = token.substring(2);
156 }
157 else if (token.startsWith("E="))
158 {
159 e = token.substring(2);
160 }
161 }
162
163
164 X509V3CertificateGenerator cg = new X509V3CertificateGenerator();
165 cg.reset();
166 cg.setIssuerDN((X509Name)issuerCert.getSubjectDN());
167 Hashtable ht = new Hashtable();
168 ht.put(X509Name.C, c);
169 ht.put(X509Name.CN, cn);
170 ht.put(X509Name.O, o);
171 cg.setSubjectDN(new X509Name(ht));
172 cg.setNotBefore(getDateArg("validFrom:"));
173 cg.setNotAfter(getDateArg("validUntil:"));
174 cg.setPublicKey(csr.getPublicKey());
175 cg.setSerialNumber(BigInteger.valueOf(1));
176 cg.setSignatureAlgorithm("MD5WITHRSA");
177
178 cg.addExtension(X509Extensions.KeyUsage.getId(), true,
179 new X509KeyUsage(
180 isLeaf ? X509KeyUsage.digitalSignature : X509KeyUsage.keyCertSign));
181
182 GeneralName gn = new GeneralName(new DERIA5String(e), 1);
183 DERConstructedSequence seq = new DERConstructedSequence();
184 seq.addObject(gn);
185 cg.addExtension(X509Extensions.SubjectAlternativeName.getId(), false,
186 new GeneralNames(seq));
187
188 Collection issuerNames = issuerCert.getSubjectAlternativeNames();
189 if (issuerNames != null) {
190 Iterator iter = issuerNames.iterator();
191 while (iter.hasNext()) {
192 List generalNames = (List) iter.next();
193
194 if (((Integer) generalNames.get(0)).intValue() == 1) {
195 Object name = generalNames.get(1);
196 DERIA5String derString;
197 if (name instanceof String) {
198 derString = new DERIA5String((String) name);
199 } else {
200 derString = new DERIA5String((byte[]) name);
201 }
202 seq = new DERConstructedSequence();
203 seq.addObject(new GeneralName(derString, 1));
204 cg.addExtension(
205 X509Extensions.IssuerAlternativeName.getId(),
206 false, new GeneralNames(seq));
207 break;
208 }
209 }
210 }
211
212 X509Certificate cert = cg.generateX509Certificate(issuerKey, "BC");
213
214
215 String fn = getArg("file:") + "_public.x509.crt";
216 System.out.println("Writing cert to " + fn + ".");
217 FileOutputStream str = new FileOutputStream(fn);
218 str.write(cert.getEncoded());
219 str.close();
220
221 System.out.println();
222 System.out.println("Done!");
223 System.out.println();
224 }
225 }